#include"pacman.h"
#include "ui_pacman.h"
#include<qrect.h>
#include<qtimer.h>
 #include<QKeyEvent>
#include<QPushButton>


pacman::pacman(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::pacman)
{
    ui->setupUi(this);
    this->hide();

    setFocusPolicy(Qt::StrongFocus);
    setFocus();
    //地图初始化
    int initMap[ROWS][COLS]={
        // 行 0-20
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 第0行（顶部墙壁）
        {1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1}, // 第1行
        {1,2,1,1,1,2,1,1,2,1,2,1,1,2,1,1,1,2,1}, // 第2行
        {1,3,1,0,1,2,1,0,2,2,2,0,1,2,1,0,1,3,1}, // 第3行（能量豆在两端）
        {1,2,1,1,1,2,1,1,2,1,2,1,1,2,1,1,1,2,1}, // 第4行
        {1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1}, // 第5行
        {1,2,1,1,1,2,1,2,1,1,1,2,1,2,1,1,1,2,1}, // 第6行
        {1,2,1,1,1,2,1,2,1,1,1,2,1,2,1,1,1,2,1}, // 第7行
        {1,2,2,2,2,2,1,2,2,2,2,2,1,2,2,2,2,2,1}, // 第8行
        {1,1,1,1,1,2,1,1,1,0,1,1,1,2,1,1,1,1,1}, // 第9行（中间分隔墙）
        {2,2,2,2,2,2,1,0,0,0,0,0,1,2,2,2,2,2,2}, // 第10行（幽灵出生区通道）
        {1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1}, // 第11行
        {1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1}, // 第12行
        {1,2,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,2,1}, // 第13行
        {1,2,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,2,1}, // 第14行
        {1,3,2,2,1,2,2,2,2,2,2,2,2,2,1,2,2,3,1}, // 第15行（能量豆）
        {1,1,1,2,1,2,1,2,1,1,1,2,1,2,1,2,1,1,1}, // 第16行
        {1,1,1,2,1,2,1,2,1,1,1,2,1,2,1,2,1,1,1}, // 第17行
        {1,2,2,2,2,2,1,2,2,2,2,2,1,2,2,2,2,2,1}, // 第18行
        {1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1}, // 第19行
        {1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1}, // 第20行
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}  // 第21行（底部墙壁）
    };



    for(int row=0;row<ROWS;++row){
        for(int col=0;col<COLS;++col){
            gameMap[row][col]=initMap[row][col];
        }
    }


    //幽灵初始化
    ghosts.append({9*CELL_SIZE,10*CELL_SIZE,Qt::Key_Left,NORMAL,Qt::red});//小红
    ghosts.append({9*CELL_SIZE,10*CELL_SIZE,Qt::Key_Right,NORMAL,Qt::cyan});//小青
    //。。。添加其他幽灵。。。

    //幽灵移动定时器
    ghostTimer=new QTimer(this);
    connect(ghostTimer,&QTimer::timeout,this,&pacman::moveGhosts);
    //ghostTimer->start(150);

    //设置游戏定时器（驱动动画和移动）
    gameTimer=new QTimer(this);
    connect(gameTimer,&QTimer::timeout,this,&pacman::gameUpdate);
    //gameTimer->start(16);

    mouthAngle=45;
    isMouthClosing=true;

    setFixedSize(COLS*CELL_SIZE,ROWS*CELL_SIZE);//固定窗口大小

    //初始化音乐播放器
    audioOutput=new QAudioOutput(this);
    musicPlayer=new QMediaPlayer(this);
    musicPlayer->setAudioOutput(audioOutput);
    musicPlayer->setSource(QUrl("qrc:/music/music/pacman_music.mp3"));
    musicPlayer->setLoops(QMediaPlayer::Infinite);
    audioOutput->setVolume(50);
    musicPlayer->play();

    connect(musicPlayer,&QMediaPlayer::errorOccurred,[](QMediaPlayer::Error error,const QString &errorString){
        qDebug()<<"音乐播放有误:"<<errorString;
    });

    //链接信号槽
    QPushButton *musicButton = new QPushButton("音乐开关",this);
    connect (musicButton,&QPushButton::clicked,[this](bool checked){
        if(checked){musicPlayer->play();}
        else{musicPlayer->pause();}

    });

    pacmanX=1*CELL_SIZE;
    pacmanY=1*CELL_SIZE;
    currentDirection=Qt::Key_Right;
    nextDirection=Qt::Key_Right;
    isMoving=false;

    /*pacmanRightImg.load(":/image/image/pacmanRight.jpg");
    pacmanLeftImg.load(":/image/image/pacmanLeft.jpg");
    pacmanUpImg.load(":/image/image/pacmanUp.jpg");
    pacmanDownImg.load(":/image/image/pacmanDown.jpg");

    ghostRedImg.load(":/image/image/ghostRed.jpg");
    ghostCyanImg.load(":/image/image/ghostyellow.jpg");*/

}

pacman::~pacman()
{
    delete ui;
}

void pacman::startGame(){
    isGameRunning=true;
    gameTimer->start(16);
    ghostTimer->start(150);
    this->show();

}

void pacman::pauseGame(){
    isGameRunning=false;
    gameTimer->stop();
    ghostTimer->stop();
}


//游戏更新
void pacman::gameUpdate(){

    movePacman();
    updateAnimation();
    checkCollisions();
    update();

}

//辅助函数
bool pacman::isAtGridCenter(){
    //允许在+=2的范围内转向，避免卡顿
    const int tolerance = PACMAN_SPEED+2;
    int centerX=pacmanX+CELL_SIZE/2;
    int centerY=pacmanY+CELL_SIZE/2;

    int gridCenterX=(centerX/CELL_SIZE)*CELL_SIZE+CELL_SIZE/2;
    int gridCenterY=(centerY/CELL_SIZE)*CELL_SIZE+CELL_SIZE/2;
    //return (pacmanX+CELL_SIZE/2==gridCenterX)&&(pacmanY+CELL_SIZE/2==gridCenterY);
    return abs(centerX-gridCenterX)<=tolerance&&
           abs(centerY-gridCenterY)<=tolerance;
  /* const int halfCell=CELL_SIZE/2;
    return (pacmanX%CELL_SIZE==halfCell)&&(pacmanY%CELL_SIZE==halfCell);*/
}

bool pacman:: canMoveToDirection(int direction){
    int nextCol=pacmanX/CELL_SIZE;
    int nextRow=pacmanY/CELL_SIZE;

    switch(direction){
    case Qt::Key_Left:nextCol--;break;
    case Qt::Key_Right:nextCol++;break;
    case Qt::Key_Up:nextRow--;break;
    case Qt::Key_Down:nextRow++;break;
    }

    if(nextCol<0)nextCol=COLS-1;
    else if(nextCol>=COLS)nextCol=0;

    //检查地图数组是否越界
    if(nextRow<0||nextRow>=ROWS||nextCol<0||nextCol>=COLS){
        return false;
    }
    return (gameMap[nextRow][nextCol]!=1);
}

bool pacman::canMoveTo(int x,int y){
    //计算吃豆人四个角的检测点
   QPoint checkPoints[4]={
        QPoint(x,y),//左上角
        QPoint(x+CELL_SIZE-1,y),//右上角
        QPoint(x,y+CELL_SIZE-1),//左下角
        QPoint(x+CELL_SIZE-1,y+CELL_SIZE-1)//右下角
    };

    for(const QPoint& point :checkPoints){
        int col=point.x()/CELL_SIZE;
        int row=point.y()/CELL_SIZE;

        if(col<0)col=COLS-1;
        else if(col>=COLS)col=0;


        /*qDebug()<<"Checking point:("<<point.x()<<","<<point.y()
                 <<")->Row:"<<row<<",Col:"<<col
                 <<",Value:"<<gameMap[row][col];*/

       // qDebug()<<"check point:("<<point.x()<<","<<point.y()<<"),Blocked:"<<(gameMap[row][col]==1);

        if(row<0||row>=ROWS||col<0||col>=COLS){
            return false;//超出地图边界
        }

        if(gameMap[row][col]==1){
            return false;
        }
    }
    return true;
}


//地图元素，0=空地，1=墙，2=豆子，3=能量豆
//int CELL_SIZE = 30;//规定每个网络单元为30*30像素
void pacman::paintEvent(QPaintEvent *event){
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,false);//关闭抗锯齿
    painter.setRenderHint(QPainter::SmoothPixmapTransform,false);//关闭平滑缩放


//绘制地图，保持硬边缘
    for(int row=0;row<ROWS;++row){
        for(int col=0;col<COLS;++col){
           //Rect cellRect(col*CELL_SIZE,row*CELL_SIZE,CELL_SIZE,CELL_SIZE);
            int x=col*CELL_SIZE;
           int y=row*CELL_SIZE;

            switch(gameMap[row][col]){
            case 1://墙壁
                painter.fillRect(x,y,CELL_SIZE,CELL_SIZE,Qt::blue);
                break;

            case 2://豆子
                painter.setBrush(Qt::yellow);
                painter.drawEllipse(x+CELL_SIZE/2-2,y+CELL_SIZE/2-2,4,4);
                break;

            case 3://能量豆
                painter.setBrush(Qt::yellow);
                painter.drawEllipse(x+CELL_SIZE/2-4,y+CELL_SIZE/2-4,8,8);
                break;


            }
        }
    }
//绘制幽灵
        for(const Ghost& ghost:ghosts){
            painter.setBrush(ghost.mode==SCARED?Qt::blue:ghost.color);
            painter.drawEllipse(ghost.x,ghost.y,CELL_SIZE,CELL_SIZE);
            //绘制眼睛方向
            painter.setBrush(Qt::white);
            switch(ghost.direction){
            case Qt::Key_Left:
                painter.drawEllipse(ghost.x+5,ghost.y+10,6,6);break;
                 painter.drawEllipse(ghost.x+5,ghost.y+20,6,6);break;
            case Qt::Key_Right:
                painter.drawEllipse(ghost.x+20,ghost.y+10,6,6);break;
                 painter.drawEllipse(ghost.x+20,ghost.y+20,6,6);break;
            case Qt::Key_Up:
                painter.drawEllipse(ghost.x+10,ghost.y+5,6,6);break;
                 painter.drawEllipse(ghost.x+20,ghost.y+5,6,6);break;
            case Qt::Key_Down:
                painter.drawEllipse(ghost.x+10,ghost.y+25,6,6);break;
                 painter.drawEllipse(ghost.x+20,ghost.y+25,6,6);break;
            default:break;
            }
        }

//绘制计分板
        painter.setPen(Qt::white);
        painter.setFont(QFont("Arial",16));
        painter.drawText(10,30,"Score:"+QString::number(score));


//绘制吃豆人
   painter.setBrush(Qt::yellow);
   painter.setPen(Qt::NoPen);

   int startAngle=0;

   //根据移动方向调整起始角度
   switch(currentDirection){
   case Qt::Key_Left:startAngle=180*16;break;
   case Qt::Key_Right:startAngle=0*16;break;
   case Qt::Key_Up:startAngle=90*16;break;
   case Qt::Key_Down:startAngle=270*16;break;
   }

    int spanAngle=(360-2*mouthAngle)*16;//跨越角度

   painter.drawPie(pacmanX,pacmanY,CELL_SIZE,CELL_SIZE,startAngle,spanAngle);
    /*    QPixmap pacmanImg;
        switch(currentDirection){
    case Qt::Key_Left:pacmanImg=pacmanLeftImg;break;
    case Qt::Key_Right:pacmanImg=pacmanRightImg;break;
    case Qt::Key_Up:pacmanImg=pacmanUpImg;break;
    case Qt::Key_Down:pacmanImg=pacmanDownImg;break;
    default:pacmanImg=pacmanRightImg;break;

}
    painter.drawPixmap(pacmanX,pacmanY,CELL_SIZE,CELL_SIZE,pacmanImg);*/
}

//定时器更新动画
void pacman::updateAnimation(){
    if(isMouthClosing){
        mouthAngle-=3;
        if(mouthAngle<=0)isMouthClosing=false;
    }
    else{
        mouthAngle+=3;
        if(mouthAngle>=45)isMouthClosing=true;
    }
    update();
}


//键盘事件处理
void pacman::keyPressEvent(QKeyEvent *event){
    //qDebug()<<"Key Pressed:"<<event->key();
    switch(event->key()){
    case Qt::Key_Left:nextDirection=Qt::Key_Left;break;
    case Qt::Key_Right:nextDirection=Qt::Key_Right;break;
    case Qt::Key_Up:nextDirection=Qt::Key_Up;break;
    case Qt::Key_Down:nextDirection=Qt::Key_Down;break;
    default:QMainWindow::keyPressEvent(event);
    }

}


//定时移动
void pacman::movePacman(){
    if(!isGameRunning)return;
    //检查下一个方向是否可以通行
    if(isAtGridCenter()){
    if(canMoveToDirection(nextDirection)){
        currentDirection=nextDirection;
       }
    }

    int newX=pacmanX;
    int newY=pacmanY;

    switch(currentDirection){
       case Qt::Key_Left:  newX-=PACMAN_SPEED;break;
       case Qt::Key_Right: newX+=PACMAN_SPEED;break;
       case Qt::Key_Up:    newY-=PACMAN_SPEED;break;
       case Qt::Key_Down:  newY+=PACMAN_SPEED;break;
    }

       if(canMoveTo(newX,newY)){
        pacmanX=newX;
        pacmanY=newY;
        isMoving=true;
       }
       else if(isAtGridCenter()){
           isMoving=false;
       }

    //穿墙逻辑
    if(pacmanX<-CELL_SIZE/2){
        pacmanX=width()-CELL_SIZE/2;
        //pacmanX=(pacmanX/CELL_SIZE)*CELL_SIZE+CELL_SIZE/2;
    }else if (pacmanX>=width()-CELL_SIZE/2){
        pacmanX=-CELL_SIZE/2;
        //pacmanX=(pacmanX/CELL_SIZE)*CELL_SIZE+CELL_SIZE/2;
    }

    //pacmanY=(pacmanY/CELL_SIZE)*CELL_SIZE+CELL_SIZE/2;

    //穿墙后重置方向状态
    if(pacmanX<-CELL_SIZE/2||pacmanX>=width()-CELL_SIZE/2){
        currentDirection=nextDirection;
        if(!canMoveToDirection(currentDirection)){
            currentDirection=Qt::Key_Right;
        }

    }

    //qDebug()<<"Moving To:("<<newX<<","<<newY<<"),Direction:"<<currentDirection;
}

//幽灵移动
void pacman::moveGhosts(){
    if(!isGameRunning)return;
    for(Ghost& ghost:ghosts){
        //简单ai：随机选择移动方向
        QVector<Qt::Key>possibleDirs;
        Qt::Key oppositeDir=Qt::Key_Left;
    switch(ghost.direction){
        case Qt::Key_Left: oppositeDir=Qt::Key_Right;break;
        case Qt::Key_Right: oppositeDir=Qt::Key_Left;break;
        case Qt::Key_Up: oppositeDir=Qt::Key_Down;break;
        case Qt::Key_Down: oppositeDir=Qt::Key_Up;break;
        default:break;
        }

        for(auto dir:{Qt::Key_Left,Qt::Key_Right,Qt::Key_Up,Qt::Key_Down}){
            if(dir!=oppositeDir&&canGhostMoveTo(ghost,dir)){
                possibleDirs.append(dir);
            }
        }
        if(!possibleDirs.isEmpty()){
            //恐慌模式下随机移动，正常模式下追踪吃豆人
            if(ghost.mode==NORMAL&&QRandomGenerator::global()->bounded(100)>30){
                //选择靠近吃豆人的方向
                Qt::Key bestDir=possibleDirs[0];
                int minDist=INT_MAX;
                for(Qt::Key dir:possibleDirs){
                    int dist=0;
                    switch(dir){
                    case Qt::Key_Left:
                        dist=abs((ghost.x-PACMAN_SPEED)-pacmanX)+abs(ghost.y-pacmanY);
                        break;
                    case Qt::Key_Right:
                        dist=abs((ghost.x+PACMAN_SPEED)-pacmanX)+abs(ghost.y-pacmanY);
                        break;
                    case Qt::Key_Up:
                        dist=abs((ghost.x)-pacmanX)+abs((ghost.y-PACMAN_SPEED)-pacmanY);
                        break;
                    case Qt::Key_Down:
                        dist=abs((ghost.x)-pacmanX)+abs((ghost.y+PACMAN_SPEED)-pacmanY);
                        break;
                    default:break;
                    }
                    if(dist<minDist){
                        minDist=dist;
                        bestDir=dir;
                    }
                }
                ghost.direction =bestDir;
            }
            else{
                ghost.direction=possibleDirs[QRandomGenerator::global()->bounded(possibleDirs.size())];
            }
        }

        //移动幽灵
    switch(ghost.direction){
        case Qt::Key_Left:ghost.x-=PACMAN_SPEED;break;
        case Qt::Key_Right:ghost.x+=PACMAN_SPEED;break;
        case Qt::Key_Up:ghost.y-=PACMAN_SPEED;break;
        case Qt::Key_Down:ghost.y+=PACMAN_SPEED;break;
        default:break;
        }

        //幽灵穿墙逻辑
        if(ghost.x<-CELL_SIZE/2){
            ghost.x=width()-CELL_SIZE/2;
        }else if (ghost.x>=width()-CELL_SIZE/2){
            ghost.x=CELL_SIZE/2;
        }
    }
}

bool pacman::canGhostMoveTo(const Ghost& ghost,Qt::Key dir){
    int nextX=ghost.x;
    int nextY=ghost.y;

   switch(dir){
      case Qt::Key_Left:  nextX-=PACMAN_SPEED;break;
      case Qt::Key_Right: nextX+=PACMAN_SPEED;break;
      case Qt::Key_Up:    nextY-=PACMAN_SPEED;break;
      case Qt::Key_Down:  nextY+=PACMAN_SPEED;break;
      default:return false;
    }

    //检查幽灵四个角的碰撞
    QPoint checkPoints[4]={
        QPoint(nextX,nextY),
        QPoint(nextX+CELL_SIZE-1,nextY),
        QPoint(nextX,nextY+CELL_SIZE-1),
        QPoint(nextX+CELL_SIZE-1,nextY+CELL_SIZE-1)
};

    for(const QPoint& point:checkPoints){
        int col=point.x()/CELL_SIZE;
        int row=point.y()/CELL_SIZE;

        if(row<0||row>=ROWS||col<0||col>=COLS){
            return false;
        }

        if(gameMap[row][col]==1){
            return false;
        }
    }
    return true;
}

//碰撞检测
void pacman::checkCollisions(){
    //豆子碰撞检测
    int centerX=pacmanX+CELL_SIZE/2;
    int centerY=pacmanY+CELL_SIZE/2;
    int col=centerX/CELL_SIZE;
    int row=centerY/CELL_SIZE;

    if(gameMap[row][col]==2){
        gameMap[row][col]=0;
        score+=10;
    }else if(gameMap[row][col]==3){
        gameMap[row][col]=0;
        score+=50;
        //触发幽灵恐慌模式
        for(Ghost& ghost:ghosts){
            ghost.mode=SCARED;
        }
        QTimer::singleShot(10000,this,[this](){
            //10s后恢复
            for(Ghost& ghost:ghosts)ghost.mode=NORMAL;
        });
    }

    //幽灵碰撞检测
    QRect pacmanRect(pacmanX,pacmanY,CELL_SIZE,CELL_SIZE);
    for(Ghost& ghost:ghosts){
        QRect ghostRect(ghost.x,ghost.y,CELL_SIZE,CELL_SIZE);
        if(pacmanRect.intersects(ghostRect)){
            if(ghost.mode==SCARED){
                ghost.x=10*CELL_SIZE;
                ghost.y=10*CELL_SIZE;
                score+=200;
            }else{
                //游戏结束处理
                QMessageBox::information(this,"Game Over","Score:"+QString::number(score));
                qApp->quit();
            }
        }
    }
}

void pacman::resetGame(){
    score=0;
    pacmanX=pacmanY=1*CELL_SIZE;
    //重置幽灵位置
    for(Ghost& ghost:ghosts){
        ghost.x=10*CELL_SIZE;
        ghost.y=10*CELL_SIZE;
    }
    memcpy(gameMap,initMap,sizeof(gameMap));
    update();
}
